package com.example.stock.service.impl;

import com.example.stock.excel.ExcelReaderUtil;
import com.example.stock.excel.StockOperate;
import com.example.stock.service.StockOperationService;
import com.example.stock.util.DataUtil;
import com.example.stock.util.DateUtil;
import com.example.stock.util.OperationConstant;
import jakarta.annotation.PostConstruct;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

@Log4j2
@Service
public class StockOperationServiceImpl implements StockOperationService {

    private String dateDayFormat(StockOperate stockOperate) {
        return DateUtil.dateDailyFormat(stockOperate.getDate());
    }

    private String dateWeekFormat(StockOperate stockOperate) {
        String formatDate = dateDayFormat(stockOperate);
        LocalDate parseDate = LocalDate.parse(formatDate);

        LocalDate monday = parseDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
        LocalDate sunday = parseDate.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));

        DateTimeFormatter pattern = DateTimeFormatter.ofPattern("MMdd");
        return parseDate.getYear() + ":" + monday.format(pattern)  + "--" + sunday.format(pattern);
    }

    private List<StockOperate> stockOperates;

    @PostConstruct
    private void init() {
        stockOperates = DataUtil.getListData(StockOperate.class, ExcelReaderUtil.FILE_OPERATION, "交易记录");
    }

    /**
     * 交易数据
     * @return
     */
    private List<StockOperate> getStockOperateData() {
        return stockOperates;
    }

    public Map<String, List<StockOperate>> operationDataGroupByDate() {
        return getStockOperateData().stream()
                .collect(Collectors.groupingBy(this::dateDayFormat));
    }

    public Map<String, List<StockOperate>> operationDataGroupByMonth() {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy--MM");
        return getStockOperateData().stream()
                .filter(item -> item.getStock() != null)
                .collect(Collectors.groupingBy(item ->  dateFormat.format(item.getDate())));
    }

    public Map<String, List<StockOperate>> operationDataGroupByStock() {
        return getStockOperateData().stream()
                .filter(item -> item.getStock() != null)
                .collect(Collectors.groupingBy(StockOperate::getStock));
    }

    @Override
    public List<String> getStockHold() {
        Map<String, List<StockOperate>> stockListMap = operationDataGroupByStock();

        List<String> ret = new ArrayList<>();
        stockListMap.forEach((stock, operates) -> {
            int hold = operates.stream()
                    .filter(stockOperate -> Arrays.asList(new String[]{OperationConstant.BUY, OperationConstant.SELL}).contains(stockOperate.getOperation()))
                    .mapToInt(StockOperate::getOperateNum).sum();

            if (hold > 0) {
                ret.add(stock);
            }
        });
        return ret.stream().distinct().collect(Collectors.toList());
    }

    @Override
    public Map<String, List<StockOperate>> getDayFormat(String stock) {
        List<StockOperate> stockOperates = operationDataGroupByStock().get(stock);
        if (Objects.isNull(stockOperates)) {
            return null;
        }
        return stockOperates.stream().collect(Collectors.groupingBy(this::dateDayFormat));
    }

    /**
     * 按周格式返回数据
     * @param stock
     * @return
     */
    public Map<String, List<StockOperate>> getWeekFormat(String stock) {
        List<StockOperate> stockOperates = operationDataGroupByStock().get(stock);
        if (Objects.isNull(stockOperates)) {
            return null;
        }

        return stockOperates.stream().collect(Collectors.groupingBy(this::dateWeekFormat));
    }

    static SimpleDateFormat monthFormat = new SimpleDateFormat("yyyy--MM");

    private String dateMonthFormat(StockOperate stockOperate) {
        return monthFormat.format(stockOperate.getDate());
    }

    /**
     * 按月格式返回数据
     * @param stock
     * @return
     */
    public Map<String, List<StockOperate>> getMonthFormat(String stock) {
        List<StockOperate> stockOperates = operationDataGroupByStock().get(stock);
        if (Objects.isNull(stockOperates)) {
            return null;
        }

        return stockOperates.stream().collect(Collectors.groupingBy(this::dateMonthFormat));
    }

    @Override
    public List<StockOperate> getOperationData() {
        return getStockOperateData();
    }

    @Override
    public List<StockOperate> getLastedOperationData() {
        return getLastedOperationData(350);
    }

    @Override
    public List<StockOperate> getLastedOperationData(int limit) {
        List<String> filterWords = Arrays.asList(new String[]{OperationConstant.WILL_BUY,OperationConstant.WILL_SELL, "总结"});

        return getStockOperateData().stream()
                .sorted(Comparator.comparing(StockOperate::getDate).reversed())
                .filter(o -> !filterWords.contains(o.getOperation()))
                .limit(limit).toList();
    }

    @Override
    public List<StockOperate> getStockOperationData(String stock) {
        return getOperationData().stream()
                .filter(i -> i.getStock() != null && i.getStock().equals(stock))
                .toList();
    }

    @Override
    public List<String> getLastedOperationStocks(int limit) {
        return getLastedOperationData(limit).stream().map(StockOperate::getStock).distinct().toList();
    }
}